package com.example.handdet;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.util.Base64;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class Base64Util {
    private static final char[] base64EncodeChars = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
            'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
            's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};

    private static byte[] base64DecodeChars = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
            61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1,
            -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1};

    private Base64Util() {
    }

    /**
     * 将字节数组编码为字符串
     *
     * @param data
     */
    public static String encode(byte[] data) {
        StringBuffer sb = new StringBuffer();
        int len = data.length;
        int i = 0;
        int b1, b2, b3;

        while (i < len) {
            b1 = data[i++] & 0xff;
            if (i == len) {
                sb.append(base64EncodeChars[b1 >>> 2]);
                sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
                sb.append("==");
                break;
            }
            b2 = data[i++] & 0xff;
            if (i == len) {
                sb.append(base64EncodeChars[b1 >>> 2]);
                sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
                sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
                sb.append("=");
                break;
            }
            b3 = data[i++] & 0xff;
            sb.append(base64EncodeChars[b1 >>> 2]);
            sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
            sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]);
            sb.append(base64EncodeChars[b3 & 0x3f]);
        }
        return sb.toString();
    }

    /**
     * 灏哹ase64瀛楃涓茶В鐮佷负瀛楄妭鏁扮粍
     *
     * @param str
     */
    public static byte[] decode(String str) throws Exception {
        byte[] data = str.getBytes("GBK");
        int len = data.length;
        ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
        int i = 0;
        int b1, b2, b3, b4;

        while (i < len) {

            /* b1 */
            do {
                b1 = base64DecodeChars[data[i++]];
            } while (i < len && b1 == -1);
            if (b1 == -1) {
                break;
            }

            /* b2 */
            do {
                b2 = base64DecodeChars[data[i++]];
            } while (i < len && b2 == -1);
            if (b2 == -1) {
                break;
            }
            buf.write((b1 << 2) | ((b2 & 0x30) >>> 4));

            /* b3 */
            do {
                b3 = data[i++];
                if (b3 == 61) {
                    return buf.toByteArray();
                }
                b3 = base64DecodeChars[b3];
            } while (i < len && b3 == -1);
            if (b3 == -1) {
                break;
            }
            buf.write(((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2));

            /* b4 */
            do {
                b4 = data[i++];
                if (b4 == 61) {
                    return buf.toByteArray();
                }
                b4 = base64DecodeChars[b4];
            } while (i < len && b4 == -1);
            if (b4 == -1) {
                break;
            }
            buf.write(((b3 & 0x03) << 6) | b4);
        }
        return buf.toByteArray();
    }


    /**
     * <p>将文件转成base64 字符串</p>
     *
     * @param path 文件路径
     * @return
     * @throws Exception
     */
    public static String encodeBase64File(String path) throws Exception {
        File file = new File(path);
        FileInputStream inputFile = new FileInputStream(file);
        byte[] buffer = new byte[(int) file.length()];
        inputFile.read(buffer);
        inputFile.close();
        //保存
        try
        {
            FileOutputStream outStream = new FileOutputStream("/storage/emulated/0/Android/data/com.haier.heaicloth/files/upload/sss2.txt",false);
            OutputStreamWriter writer = new OutputStreamWriter(outStream,"gb2312");
            writer.write(Base64Util.encode(buffer));
            writer.close();//记得关闭

            outStream.close();
        }
        catch (Exception e)
        {
            Log.e("Base64Util", "file write error");
        }
        return Base64Util.encode(buffer);
    }

    //拍照保存本地图
    public  static  String DEFAULT_COMPRESSED_FILE_PATH="/mnt/sdcard/GestureImg/nanodet_five_2021-07-21_16_08_28_.jpg";
    // imageId 对应imageUrl

    public  static  String DEFAULT_UPLOAD_FILE_URL="";

    public static String DEFAULT_BLUR_FILE_PATH="";

    /**
     * 图片等比缩放到最小边500px
     */
    public static boolean decodeScaleBitmapToFile(File sourceFile,File targetFile) {
        Log.d("MainCameraActivity", "decode in...");
        int minPx = 500;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 通过这个bitmap获取图片的宽和高
        Bitmap bitmap = BitmapFactory.decodeFile(sourceFile.getAbsolutePath(), options);
        if (bitmap == null) {
            Log.d("Base64Util", "...bitmap为空");
        }
        float realWidth = options.outWidth;
        float realHeight = options.outHeight;
        Log.d("Base64Util", "before compress height: " + realHeight + " width :" + realWidth);
        // 计算缩放比
        int scale = (int) ((Math.min(realHeight, realWidth)) / minPx);
        Log.d("Base64Util", "compute scale：" + scale);
        if (scale <= 0) {
            scale = 1;
        }
        options.inSampleSize = scale;
        options.inJustDecodeBounds = false;
        // 注意这次要把options.inJustDecodeBounds 设为 false,这次图片是要读取出来的。
        bitmap = BitmapFactory.decodeFile(sourceFile.getAbsolutePath(), options);
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        Log.d("Base64Util", "compressed height : " + h + "width :" + w);
        //write bitmap to file
        try {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 95, stream);
            bitmap.recycle();
            FileOutputStream fos=new FileOutputStream(targetFile);
            Log.d("MainCameraActivity", " write compressed to file ");
            DEFAULT_COMPRESSED_FILE_PATH=targetFile.getAbsolutePath();
            fos.write(stream.toByteArray());
            fos.flush();
            fos.close();
            stream.close();
            Log.d("Base64Util", "write compressed to file ");
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.d("MainCameraActivity", "decode out...");

        return true;
    }
    /**
     * 图片等比缩放到最大边800*800px
     */
    public static boolean decodeScaleBitmapToFileNew(File sourceFile,File targetFile) {
        Log.d("MainCameraActivity", "decode in...");
        float maxPx = 800f;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 通过这个bitmap获取图片的宽和高
        Bitmap bitmap = BitmapFactory.decodeFile(sourceFile.getAbsolutePath(), options);
        if (bitmap == null) {
            Log.d("Base64Util", "...bitmap为空");
        }
        float realWidth = options.outWidth;
        float realHeight = options.outHeight;
        Log.d("Base64Util", "before compress height: " + realHeight + " width :" + realWidth);
        // 计算缩放比

        float fscale=((Math.max(realHeight, realWidth)) / maxPx);

        Log.d("Base64Util", "compute fscale：" + fscale);
        int scale = (int)Math.ceil(fscale);
        Log.d("Base64Util", "compute scale：" + scale);
        if (scale <= 0) {
            scale = 1;
        }
        options.inSampleSize = scale;
        options.inJustDecodeBounds = false;
        // 注意这次要把options.inJustDecodeBounds 设为 false,这次图片是要读取出来的。
        bitmap = BitmapFactory.decodeFile(sourceFile.getAbsolutePath(), options);
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        Log.d("Base64Util", "compressed height : " + h + "width :" + w);
        //write bitmap to file
        try {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 95, stream);
            bitmap.recycle();
            FileOutputStream fos=new FileOutputStream(targetFile);
            Log.d("Base64Util", " write compressed to file ");
            DEFAULT_COMPRESSED_FILE_PATH=targetFile.getAbsolutePath();
            fos.write(stream.toByteArray());
            fos.flush();
            fos.close();
            stream.close();
            Log.d("Base64Util", "write compressed to file ");
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.d("Base64Util", "decode out...");

        return true;
    }

    /**
     * 图片裁剪宽度屏幕1/3
     */
    public static boolean decodeScaleBitmapToFileCut(File sourceFile,File targetFile,int desWidth,int desHeight) {
        Log.d("Base64Util", "decode in...");
        float maxPx = 800f;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 通过这个bitmap获取图片的宽和高
        Bitmap bitmap = BitmapFactory.decodeFile(sourceFile.getAbsolutePath(), options);
        if (bitmap == null) {
            Log.d("Base64Util", "...bitmap为空");
        }
        float realWidth = options.outWidth;
        float realHeight = options.outHeight;
        Log.d("Base64Util", "before cut height: " + realHeight + " width :" + realWidth);
        int outPutWidth = 0;
        int outPutHeight = 0;
        if(realWidth>=desWidth){
            outPutWidth=desWidth;
        }
        if(realHeight>=desHeight){
            outPutHeight=desHeight;
        }
        options.inJustDecodeBounds = false;
       // options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        bitmap = BitmapFactory.decodeFile(sourceFile.getAbsolutePath(), options);

        Matrix m = new Matrix();
        m.postScale(1, 1);

       // Bitmap newBitmap = Bitmap.createBitmap(bitmap,desWidth,0,outPutWidth,outPutHeight,m,false);
        Bitmap newBitmap = Bitmap.createBitmap(bitmap, bitmap.getWidth() / 3, 0, bitmap.getWidth() / 3, bitmap.getHeight(),
                m, true);
        int w = newBitmap.getWidth();
        int h = newBitmap.getHeight();
        Log.d("Base64Util", "cut height : " + h + "width :" + w);
        //write bitmap to file
        try {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            newBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
            newBitmap.recycle();
            bitmap.recycle();
            FileOutputStream fos=new FileOutputStream(targetFile);
            //Log.d("MainCameraActivity", " write cutFile to file ");
            DEFAULT_COMPRESSED_FILE_PATH=targetFile.getAbsolutePath();
            fos.write(stream.toByteArray());
            fos.flush();
            fos.close();
            stream.close();
            Log.d("Base64Util", "write cutFile to file ");
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.d("MainCameraActivity", "decode out...");

        return true;
    }

    /**
     * 图片等比缩放到最大边800*800px
     */
    public static boolean decodeScaleBitmapToFileForBlur(File sourceFile,File targetFile) {
        Log.d("Base64Util", "decode in...");
        float maxPx = 800f;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 通过这个bitmap获取图片的宽和高
        Bitmap bitmap = BitmapFactory.decodeFile(sourceFile.getAbsolutePath(), options);
        if (bitmap == null) {
            Log.d("Base64Util", "...bitmap为空");
        }
        float realWidth = options.outWidth;
        float realHeight = options.outHeight;
        Log.d("Base64Util", "before compress height: " + realHeight + " width :" + realWidth);
        // 计算缩放比

        float fscale=((Math.max(realHeight, realWidth)) / maxPx);

        Log.d("Base64Util", "compute fscale：" + fscale);
        int scale = (int)Math.ceil(fscale);
        Log.d("Base64Util", "compute scale：" + scale);
        if (scale <= 0) {
            scale = 1;
        }
        options.inSampleSize = scale;
        options.inJustDecodeBounds = false;
        // 注意这次要把options.inJustDecodeBounds 设为 false,这次图片是要读取出来的。
        bitmap = BitmapFactory.decodeFile(sourceFile.getAbsolutePath(), options);
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        Log.d("Base64Util", "compressed height : " + h + "width :" + w);
        //write bitmap to file
        try {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 95, stream);
            bitmap.recycle();
            FileOutputStream fos=new FileOutputStream(targetFile);
            Log.d("Base64Util", " write compressed to file ");
            DEFAULT_BLUR_FILE_PATH=targetFile.getAbsolutePath();
            fos.write(stream.toByteArray());
            fos.flush();
            fos.close();
            stream.close();
            Log.d("Base64Util", "write compressed to file ");
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.d("Base64Util", "decode out...");

        return true;
    }
    /**
     * 单边压缩 压缩面积用于模糊
     * */
    public static Bitmap decodeFileToBitMap(String sourceFileAbsPath){
        float maxPx = 800f;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 通过这个bitmap获取图片的宽和高
        Bitmap bitmap = BitmapFactory.decodeFile(sourceFileAbsPath, options);
        if (bitmap == null) {
            Log.d("Base64Util", "...bitmap为空");
        }
        float realWidth = options.outWidth;
        float realHeight = options.outHeight;
        Log.d("Base64Util", "before compress height: " + realHeight + " width :" + realWidth);
        // 计算缩放比

        float fscale=((Math.max(realHeight, realWidth)) / maxPx);

        Log.d("Base64Util", "compute fscale：" + fscale);
        int scale = (int)Math.ceil(fscale);
        Log.d("Base64Util", "compute scale：" + scale);
        if (scale <= 0) {
            scale = 1;
        }
        options.inSampleSize = scale;
        options.inJustDecodeBounds = false;
        // 注意这次要把options.inJustDecodeBounds 设为 false,这次图片是要读取出来的。
        bitmap = BitmapFactory.decodeFile(sourceFileAbsPath, options);
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        return  bitmap;
    }


   public static File decodeBase64ToFile(String base64Str,String outFileName) throws IOException {

        File file=new File(outFileName);
       FileOutputStream write = new FileOutputStream(file);
       byte[] decoderBytes = Base64.decode(base64Str,Base64.DEFAULT);
       write.write(decoderBytes);
       write.close();
     return file;
   }

}
